/* 
 * File:   fsp.c
 * Author: blaze
 *
 * Version: 0.3
 *
 * Created on December 15, 2010, 2:32 PM
 * Last edit on December 16, 2010, 1:55 PM
 *
 * Full name: file server process
 *
 * Info:
 * This process is used in combination of the CHP (Client Handler Process).
 * The main function of this process is to create the map file for handling downloads.
 * It also writes files that users will upload, and send files back that users download.
 *
 * Might be important things to do if time left:
 * Put some functions in different .c files, but seeing as that has no high priority, not right now.
 */

//includes
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h> //filecontrol (open, write, etc.)
#include <semaphore.h> //semaforen
#include <sys/mman.h> //memory map files dingen
#include <string.h>
#include <pthread.h>
#include <unistd.h> //mutexes
#include "hfile.h"
//end of includes

//global defines of rights, generic sizes and filepaths/names
#define ACC_RIGHT 0600
#define COMCHANNEL "/tmp/commchan.bin" //map file for communication between CHP and FSP
#define DOWNMAPFILE "/tmp/mmappeddownload.bin" //map file for downloads
//end of global defines

//global variables, like mutexes and semaphores
//pthread_mutex_t mutexUpFull;
//pthread_mutex_t mutexDownEmpty;
//pthread_mutex_t mutexComChanRead;
//pthread_mutex_t mutexComChanPost;
int commChanfd = 0; //file descriptor to use with the communication channel between FSP and CHP
int downfd = 0; //download file descriptor to use with MMF
int upfd = 0; //upload file descriptor to use with MMF
sem_t *semComChanRead;
sem_t *semComChanPost;
sem_t *semDownFull;
sem_t *semDownEmpty;
sem_t *semUpFull;
sem_t *semUpEmpty;
//end of global variables

//prototypes
int handleUpload(char *pathname, char *filename);
int handleDownload(char *pathname, char *filename);
//end of prototypes

//MAIN PROGRAM
int main(void)
{
    //variables
    int client = 0; //not sure if this is going to be used, checks who is uploading/downloading what    
    int bytesWritten = 0; //a check to see how many bytes were written to an FD
    int result = 0; //a check for the lseek "stretch"
    char *comMap; //communication mmap
    int i = 0; //for generic for loops
    int amountSplit = 0;//for knowing how many words there are from the split
    char buffer[BUFLEN];
    //end of variables   
    openSem();
    createDownMap();
    
    while(1)
    {
        //MUTEX AND SEMAPHORES CHECKS HERE
        //wait for the commchanel semaphore
        if((sem_wait(semComChanPost))<0)
        {
            perror("sem_wait");
        }
        //end of wait
        //END OF MUTEX AND SEMAPHORES CHECKS
        
        //open the communication channel for IPC, CHP should create it because he is the first to talk to the FSP
        commChanfd = open(COMCHANNEL, O_RDWR, ACC_RIGHT);
        if(commChanfd < 0)
        {
            perror("Could not open the communication channel!");
        }
        //end of communication channel opening

        //map the comm channel
        comMap = (char *)mmap(0, FILESIZE, PROT_READ, MAP_SHARED, commChanfd, 0);
        if (comMap == MAP_FAILED) {
            close(commChanfd);
            perror("Error mmapping the file");
            exit(EXIT_FAILURE);
        }
        //!!DEBUGGING!!
        printf("comMap: %s", comMap);
        //return 0;
        //!!DEBUGGING!!
        //end of comm channel map

        //read the comMap
        //split the comMap up in pieces
        printf("going to split now\n");
        commandAna(comMap, commChanfd);
        close(commChanfd);
        //end of split
        //end of read
    }

    //if all is ok, this will never be reached, and it should never be reached
    return 0;
}
//END OF MAIN PROGRAM

/*
 * openSem: open semaphores
 * Info:
 * This function is used to create and open all semaphores that will be used in the program
 */
int openSem()
{
    //pre-emptive unlinking to prevent errors
    sem_unlink("semComChanRead");
    //sem_unlink("semComChanPost");
    sem_unlink("semDownFull");
    sem_unlink("semUpEmpty");
    //end of unlinking
    if((semComChanRead = sem_open("semComChanRead", O_CREAT, 0644, 0))== SEM_FAILED)
    {
        perror("semopen semComChanRead: ");
    }
    if((semComChanPost = sem_open("semComChanPost", 0, 0644, 0))== SEM_FAILED)
    {
        perror("semopen semComChanPost: ");
    }
    if((semDownFull = sem_open("semDownFull", O_CREAT, 0644, 0))== SEM_FAILED)
    {
        perror("semopen semDownFull: ");
    }
    if((semUpEmpty = sem_open("semUpEmpty", O_CREAT,  0644, 0))== SEM_FAILED)
    {
        perror("semopen semUpEmpty: ");
    }
    //end of initialization of mutexes and semaphores
    return 0;
}
//END OF OPENSEM

/*
 * createDownMap: Creates the download map file
 * Info:
 * This function is used to create the download map file, which will be opening by download.c
 */
int createDownMap()
{
//create our download memory map file
    downfd = open(DOWNMAPFILE, O_RDWR | O_CREAT | O_TRUNC, ACC_RIGHT);
    if(downfd < 0)
    {
        perror("Could not open the download file!");
        exit(EXIT_FAILURE);
    }
    //end of download memory map file creation
    return 0;
}